package lego.jbv;

import lego.animal.IAnimal;
import lejos.nxt.LCD;
import lejos.nxt.Sound;
import lejos.nxt.comm.*;
import lejos.util.Delay;

import java.io.*;
import java.util.ArrayList;

public class BTController extends Thread {
	private static String connected = "BT: Connected";
	private static String waiting = "BT: Waiting...";
	private static String closing = "BT: Closing...";
	private boolean stopNow = false;

	private BTConnection btc;
	private DataInputStream dis;
	private DataOutputStream dos;
	private IAnimal animal;
	private Driver driver;
	private SoundController soundController;

	private static ArrayList<String> messages;

	public BTController(ArrayList<String> messages, IAnimal animal, Driver driver, SoundController soundController) {
		this.driver = driver;
		this.messages = messages;
		btc = null;
		this.animal = animal;
		this.soundController = new SoundController();
		setDaemon(true);
	}

	public void run() {
		Display.setStatus(waiting);

		btc = Bluetooth.waitForConnection();

		Display.setStatus(connected);

		dis = btc.openDataInputStream();
		dos = btc.openDataOutputStream();

		while (!stopNow) {
			read();
			send();
			
			Thread.yield();
		}
	}

	private void read() {
		int i = 0;
		try {
			while (0 < dis.available()) {
				int length = dis.readInt();
				byte[] readCommand = new byte[length];
				dis.readFully(readCommand);
				String command = new String(readCommand, "UTF-8");

				switch (command.charAt(0)) {
				case BTCommand.HIT:
					soundController.playSound(animal.getWin());
					animal.getHit();

					Display.setLife(Display.getLife() + 25);
					Display.setStatus("HIT");
					
					break;

				case BTCommand.MISS:
					Display.setLife(Display.getLife() -5);
					Display.setStatus("MISS");
					break;

				case BTCommand.LIFE:
					insertMessage(BTCommand.LIFE + String.valueOf(animal.getLife()));
					break;

				case BTCommand.STAMINA:
					insertMessage(BTCommand.STAMINA + String.valueOf(animal.getStamina()));
					break;

				case BTCommand.DRIVE:
					driver.drive(Integer.parseInt(command.substring(1,
							command.indexOf(','))), Integer.parseInt(command
							.substring(command.indexOf(',') + 1)));
					break;
					
				case BTCommand.NAME:
					insertMessage(BTCommand.NAME + animal.getName());
					break;
					
				case BTCommand.WIN:
					soundController.playSound(animal.getWin());
					Display.setStatus("I'm full");
					driver.exit();
					
					break;
					
				case BTCommand.LOSS:
					soundController.playSound(animal.getLose());
					Display.setStatus("SOO HUNGRY!!!");
					driver.exit();
					
					break;
				
				default:
					break;
				}
			}
		}

		catch (IOException e) {
			Display.setStatus("BT: Error reading");
		}

		Delay.msDelay(10);
	}

	private void send() {
		while (0 < messages.size()) {
			String msg = nextMessage();

			if (msg != null) {
				try {
					dos.writeInt(msg.getBytes("UTF-8").length);
					dos.write(msg.getBytes("UTF-8"));
					dos.flush();
				}

				catch (IOException e) {
					Display.setStatus("BT: SEND ERROR");
				}
			}
		}
	}

	public void stop() {
		stopNow = true;
		Display.setStatus(closing);

		try {
			dis.close();
			Thread.sleep(100); // wait for data to drain
			btc.close();
		} catch (Exception e) {
			Display.setStatus("BT: Stop fail");
		}

		try {
			Thread.sleep(1000);
		} catch (Exception e) {
		}
	}

	private synchronized String nextMessage() {
		String content = null;

		if (0 < messages.size()) {
			content = messages.get(0);
			messages.remove(0);
		}

		return content;
	}
	
	private synchronized void insertMessage(String content)
	{
		if(content != null && content != "")
		{
			messages.add(content);
		}
	}
}